package pl.kosmowska.ewelina.client.views.impl;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import pl.kosmowska.ewelina.client.Constants;
import pl.kosmowska.ewelina.client.ViewMessages;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.CategoryDataProxy;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.CategoryItemDataProxy;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.OutcomeDataProxy;
import pl.kosmowska.ewelina.client.views.OutcomeEditView;
import pl.kosmowska.ewelina.client.views.widgets.MessageDialogBox;
import pl.kosmowska.ewelina.client.views.widgets.dialogs.OptionEvent;
import pl.kosmowska.ewelina.client.views.widgets.dialogs.OptionEventHandler;
import pl.kosmowska.ewelina.client.views.widgets.dialogs.ThreeOptionDialog;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DoubleBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;

public class OutcomeEditViewImpl extends Composite implements OutcomeEditView {

	private static OutcomeEditViewImplUiBinder uiBinder = GWT
			.create(OutcomeEditViewImplUiBinder.class);
	@UiField
	Button confirmButton;
	@UiField
	Button clearButton;
	@UiField
	HorizontalPanel datePanel;
	@UiField
	Label warningLabel;
	@UiField
	TextBox nameBox;
	@UiField
	DoubleBox valueBox;
	@UiField
	ListBox categoryBox;
	@UiField
	ListBox priorityBox;
	@UiField
	ListBox repeatFrequencyBox;
	@UiField
	CheckBox repeatCheckBox;
	@UiField
	Panel repeatEndDatePanel;
	DateBox dateBox;
	DateBox repeatEndDateBox;
	private ThreeOptionDialog optionDialog;

	private Presenter presenter;
	private boolean alreadyInit;
	private OutcomeDataProxy outcomeData;
	private List<CategoryDataProxy> categoryDataList;
	private boolean isRepeatedOutcomeToEdit = false;
	private boolean isOutcome;
	private String name;
	private float value;
	private long interval;
	private String category;
	private String priority;
	private Date repeatEndDate;
	private int repeatFrequencyBoxIndex;
	private Date date;

	public boolean isOutcome() {
		return isOutcome;
	}

	@Override
	public void setOutcome(boolean isOutcome) {
		this.isOutcome = isOutcome;
	}

	interface OutcomeEditViewImplUiBinder extends
			UiBinder<Widget, OutcomeEditViewImpl> {
	}

	public OutcomeEditViewImpl() {
		initWidget(uiBinder.createAndBindUi(this));
	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}

	@Override
	public void reInitView() {
		dateBox = new DateBox();
		datePanel.clear();
		datePanel.add(initDateBox(dateBox, "Data:"));
		repeatEndDateBox = new DateBox();
		repeatEndDatePanel.clear();
		repeatEndDatePanel.add(initDateBox(repeatEndDateBox,
				"Powtarzaj do:"));
		initPriorityBox();
		initRepeatFrequencyBox();
		presenter.loadCategories();
		repeatEndDateBox.setEnabled(false);
		repeatFrequencyBox.setEnabled(false);
		if ((outcomeData != null)
				&& (outcomeData.getCategory()
						.equals(Constants.SAVINGS_CATEGORY)))
			isOutcome = true;
		if (outcomeData != null) {
			fillForm();
		} else {
			clearView();
		}
	}

	private void clearView() {
		nameBox.setValue(null);
		valueBox.setValue(null);
		dateBox.setValue(null);
		priorityBox.setSelectedIndex(0);
		repeatEndDateBox.setEnabled(false);
		repeatCheckBox.setValue(false);
		repeatFrequencyBox.setEnabled(false);
		isRepeatedOutcomeToEdit = false;
	}

	private void initPriorityBox() {
		priorityBox.clear();
		priorityBox.addItem("Niski");
		priorityBox.addItem("Średni");
		priorityBox.addItem("Wysoki");
	}

	private void initRepeatFrequencyBox() {
		repeatFrequencyBox.clear();
		repeatFrequencyBox.addItem("Codziennie");
		repeatFrequencyBox.addItem("Co tydzień");
		repeatFrequencyBox.addItem("Co dwa tygodnie");
		repeatFrequencyBox.addItem("Co miesiąc");
		repeatFrequencyBox.addItem("Co kwartał");
	}

	private HorizontalPanel initDateBox(DateBox dateBox, String name) {
		DateTimeFormat dateFormat = DateTimeFormat
				.getFormat(DateTimeFormat.PredefinedFormat.YEAR_MONTH_DAY);
		dateBox.setFormat(new DateBox.DefaultFormat(dateFormat));
		HorizontalPanel vPanel = new HorizontalPanel();
		Label label = new Label(name);
		label.setWidth("100px");
		vPanel.add(label);
		vPanel.add(dateBox);
		return vPanel;
	}

	private void initCategoryBox() {
		categoryBox.clear();
		if (categoryDataList != null) {
			Iterator<CategoryDataProxy> itrCategory = categoryDataList
					.iterator();
			if (itrCategory != null) {
				while (itrCategory.hasNext()) {
					CategoryDataProxy currentCategory = itrCategory.next();
					List<CategoryItemDataProxy> currentItemList = currentCategory
							.getItems();
					if (currentItemList != null) {
						Iterator<CategoryItemDataProxy> itrCategoryItem = currentItemList
								.iterator();
						if (itrCategoryItem != null) {
							while (itrCategoryItem.hasNext()) {
								categoryBox.addItem(currentCategory.getName()
										+ ":"
										+ itrCategoryItem.next().getName());
							}
						}
					}
				}
			}
		}

	}

	@Override
	public void setData(OutcomeDataProxy outcomeData) {
		this.outcomeData = outcomeData;
	}

	private void fillForm() {
		nameBox.setText(outcomeData.getName());
		float value;
		if (isOutcome)
			value = -abs(outcomeData.getValue());
		else
			value = abs(outcomeData.getValue());
		valueBox.setValue((double) value);
		dateBox.setValue(outcomeData.getDate());
		int index = 0;
		if (outcomeData.getPriority().equals("Wysoki"))
			index = 2;
		else if (outcomeData.getPriority().equals("Sredni"))
			index = 1;
		else
			index = 0;
		priorityBox.setSelectedIndex(index);
		if (outcomeData.isMultiple()) {
			isRepeatedOutcomeToEdit = true;
			repeatEndDateBox.setValue(outcomeData.getRepeatEndDate());
			repeatCheckBox.setValue(true);
			repeatFrequencyBox.setItemSelected(outcomeData.getRepeatInterval(),
					true);
			repeatFrequencyBox.setEnabled(true);
			repeatEndDateBox.setEnabled(true);
		} else {
			repeatEndDateBox.setEnabled(false);
			repeatCheckBox.setValue(false);
			repeatFrequencyBox.setEnabled(false);
		}

	}

	private float abs(float value) {
		if (value > 0)
			return value;
		else
			return (-value);
	}

	private void fillCategoryBox() {
		categoryBox.setSelectedIndex(0);
		if (outcomeData != null)
			for (int i = 0; i < categoryBox.getItemCount(); i++) {
				if (categoryBox.getValue(i).equals(outcomeData.getCategory())) {
					categoryBox.setSelectedIndex(i);
					break;
				}
			}

	}

	public void initSavingsOptionDialog() {
		if (optionDialog == null) {
			optionDialog = new ThreeOptionDialog(
					"Szacowana wartość przychodu nie pozwoli na pokrycie tego wydatku. Wybierz opcję finansowania wydatku.");
			optionDialog.setOptionsText("Pozostaw ujemne saldo w tym miesącu",
					"Stwórz plan oszczędzania", "Weź na kredyt");
			optionDialog.addSelectionHandler(new OptionEventHandler() {
				public void onOptionEvent(OptionEvent event) {
					if (event.getOptionEvent() == OptionEvent.Selected.OPTION_1) {
						presenter.saveSingleOutcomeData(name, value, category,
								date, priority, null);
					} else if (event.getOptionEvent() == OptionEvent.Selected.OPTION_2) {
						presenter.generateSavingsPlan(name, value, category,
								date, priority);
					} else if (event.getOptionEvent() == OptionEvent.Selected.OPTION_3) {
						presenter.generateLoan(name, value, category, date,
								priority);
					} else if (event.getOptionEvent() == OptionEvent.Selected.FALSE) {
						// do nothing
					}
				}
			});
		}
		optionDialog.center();
	}

	private void process(List<CategoryDataProxy> categoryDataList) {
		this.categoryDataList = categoryDataList;
	}

	@UiHandler("confirmButton")
	void onConfirmButtonClick(ClickEvent event) {
		if (!validate(nameBox) || !validate(valueBox) || !validate(dateBox)) {
			showMessage(ViewMessages.ERROR_WRONG_INPUT);
			return;
		}

		name = nameBox.getText();
		value = valueBox.getValue().floatValue();
		if (isOutcome)
			value = -abs(value);
		else
			value = abs(value);
		date = dateBox.getValue();
		category = categoryBox.getValue(categoryBox.getSelectedIndex());
		priority = priorityBox.getValue(priorityBox.getSelectedIndex());
		boolean checked = repeatCheckBox.getValue();
		repeatEndDate = repeatEndDateBox.getValue();
		repeatFrequencyBoxIndex = repeatFrequencyBox.getSelectedIndex();
		interval = 0;
		long day = 24 * 60 * 60 * 1000;
		switch (repeatFrequencyBoxIndex) {
		case 0:
			interval = day;
			break;
		case 1:
			interval = 7 * day;
			break;
		case 2:
			interval = 14 * day;
			break;
		case 3:
			interval = 0;
			break;// month
		case 4:
			interval = 1;
			break; // quarter
		}
		if ((outcomeData != null)
				&& (outcomeData.getCategory()
						.equals(Constants.SAVINGS_CATEGORY))) {
			presenter.reInitSavingsPlan(valueBox.getValue().floatValue());
		} else if (checked) {
			if (!validate(date, repeatEndDate)) {
				showMessage(ViewMessages.ERROR_WRONG_DATES);
				return;
			}
			if (isRepeatedOutcomeToEdit)
				initEditOptionDialog();
			else
				presenter.saveRepeatedOutcomeData(name, value, category, date,
						priority, repeatEndDate, interval,
						repeatFrequencyBoxIndex);
		} else {
			if (!isOutcome)
				presenter.saveSingleOutcomeData(name, value, category, date,
						priority, null);
			else
				presenter.saveIfBalancePositive(name, value, category, date,
						priority);
		}
	}

	private boolean validate(Date startDate, Date endDate) {
		if (startDate.getTime() > endDate.getTime())
			return false;
		else
			return true;
	}

	private boolean validate(DateBox dateBox) {
		if (dateBox.getValue() == null)
			return false;
		else
			return true;
	}

	private boolean validate(DoubleBox doubleBox) {
		if (doubleBox.getValue() == null)
			return false;
		else
			return true;
	}

	private boolean validate(TextBox textbox) {
		if (textbox.getText() == null || textbox.getText().equals(""))
			return false;
		else
			return true;
	}

	private void initEditOptionDialog() {
		if (optionDialog == null) {
			optionDialog = new ThreeOptionDialog(
					"Zaznaczyles powtarzajacy wydatek do edycji. Co chcesz z nim zrobic?");
			optionDialog.setOptionsText("Zmien pojedynczy",
					"Zmien wszystkie w serii", "Zmien wszystkie nastepne");
			optionDialog.addSelectionHandler(new OptionEventHandler() {
				public void onOptionEvent(OptionEvent event) {
					if (event.getOptionEvent() == OptionEvent.Selected.OPTION_1) {
						presenter.saveSingleOutcomeData(name, value, category,
								date, priority, null);
					} else if (event.getOptionEvent() == OptionEvent.Selected.OPTION_2) {
						presenter.editAllRepeatedOutcomeData(name, value,
								category, date, priority, repeatEndDate,
								interval, repeatFrequencyBoxIndex);
					} else if (event.getOptionEvent() == OptionEvent.Selected.OPTION_3) {
						presenter.editFollowingRepeatedOutcomeData(name, value,
								category, date, priority, repeatEndDate,
								interval, repeatFrequencyBoxIndex);
					} else if (event.getOptionEvent() == OptionEvent.Selected.FALSE) {
						// do nothing
					}
				}
			});
		}
		optionDialog.center();
	}

	@UiHandler("repeatCheckBox")
	void onRepeatCheckBoxClick(ClickEvent event) {
		boolean checked = ((CheckBox) event.getSource()).getValue();
		if (checked) {
			repeatEndDateBox.setEnabled(true);
			repeatFrequencyBox.setEnabled(true);
		} else {
			repeatEndDateBox.setEnabled(false);
			repeatFrequencyBox.setEnabled(false);
		}
	}

	@Override
	public void initCategoryList(List<CategoryDataProxy> categoryDataList) {
		process(categoryDataList);
		initCategoryBox();
		fillCategoryBox();
	}

	@Override
	public void showMessage(String errorMessage) {
		MessageDialogBox messageDialogBox = new MessageDialogBox(errorMessage);
		messageDialogBox.center();
		messageDialogBox.show();

	}

	@Override
	public boolean isAlreadyInit() {
		return alreadyInit;
	}

	@Override
	public void setAlreadyInit(boolean alreadyInit) {
		this.alreadyInit = alreadyInit;
	}

	@UiHandler("clearButton")
	void onClearClick(ClickEvent event) {
		clearView();
	}

}
